Skip to content

fix(gitlab): add missing repos scope in project_mapping#8743

Merged
klesh merged 1 commit into
apache:mainfrom
spiffaz:fix/gitlab-project-mapping-repos
Mar 2, 2026
Merged

fix(gitlab): add missing repos scope in project_mapping#8743
klesh merged 1 commit into
apache:mainfrom
spiffaz:fix/gitlab-project-mapping-repos

Conversation

@spiffaz
Copy link
Copy Markdown
Contributor

@spiffaz spiffaz commented Mar 1, 2026

Summary

  • GitLab's makeScopeV200 did not create a repos scope when scopeConfig.Entities was empty or only contained CROSS, causing project_mapping to have no table='repos' row
  • This broke downstream DORA metrics, PR-issue linking, and all Grafana PR dashboard panels that join on project_mapping with table='repos'
  • The fix aligns GitLab with the GitHub plugin's makeScopesV200 (lines 155-160) by:
    1. Defaulting empty entities to plugin.DOMAIN_TYPES
    2. Adding DOMAIN_TYPE_CROSS to the repo scope condition

Closes #8742

Changes

  • backend/plugins/gitlab/api/blueprint_v200.go - two-line fix in makeScopeV200
  • backend/plugins/gitlab/api/blueprint_V200_test.go - two new test cases:
    • TestMakeScopesWithEmptyEntities - verifies empty entities default to all domain types
    • TestMakeScopesWithCrossEntity - verifies CROSS entity triggers repo scope creation

Test plan

  • All existing tests pass (TestMakeScopes, TestMakeDataSourcePipelinePlanV200)
  • New tests pass for both empty entities and CROSS entity scenarios
  • Tests verified in mericodev/lake-builder:latest Docker container (same as CI)

Note

The same issue also affects Bitbucket (missing empty default) and Azure DevOps (missing both). If this fix is accepted, I am happy to submit follow-up PRs for those plugins.

GitLab's makeScopeV200 did not create a repos scope when
scopeConfig.Entities was empty or only contained CROSS. This
caused project_mapping to have no table='repos' row, breaking
downstream DORA metrics, PR-issue linking, and all PR dashboard
panels that join on project_mapping.

The fix aligns GitLab with the GitHub plugin by:
1. Defaulting empty entities to plugin.DOMAIN_TYPES
2. Adding DOMAIN_TYPE_CROSS to the repo scope condition

Closes apache#8742
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. component/plugins This issue or PR relates to plugins pr-type/bug-fix This PR fixes a bug severity/p0 This bug blocks key user journey and function labels Mar 1, 2026
Copy link
Copy Markdown
Contributor

@klesh klesh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
Thanks for your contribution.

@klesh klesh merged commit a21382a into apache:main Mar 2, 2026
14 checks passed
spiffaz added a commit to spiffaz/incubator-devlake that referenced this pull request Mar 3, 2026
…pesV200

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopesV200 produced zero scopes,
leaving project_mapping with no repo rows. This adds the same
empty-entities default applied to GitLab in apache#8743.

Closes apache#8748
spiffaz added a commit to spiffaz/incubator-devlake that referenced this pull request Mar 3, 2026
…in makeScopeV200

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopeV200 produced zero scopes,
leaving project_mapping with no rows. Additionally, the repo scope
condition did not check for DOMAIN_TYPE_CROSS, so selecting only
CROSS would not create a repo scope, breaking DORA metrics.

This adds the same fixes applied to GitLab in apache#8743.

Closes apache#8749
klesh pushed a commit that referenced this pull request Mar 5, 2026
…in makeScopeV200 (#8751)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopeV200 produced zero scopes,
leaving project_mapping with no rows. Additionally, the repo scope
condition did not check for DOMAIN_TYPE_CROSS, so selecting only
CROSS would not create a repo scope, breaking DORA metrics.

This adds the same fixes applied to GitLab in #8743.

Closes #8749
klesh pushed a commit that referenced this pull request Mar 6, 2026
…pesV200 (#8750)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopesV200 produced zero scopes,
leaving project_mapping with no repo rows. This adds the same
empty-entities default applied to GitLab in #8743.

Closes #8748
lrf-nitro pushed a commit to AkerBP/nitro-devlake that referenced this pull request Mar 9, 2026
…in makeScopeV200 (apache#8751)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopeV200 produced zero scopes,
leaving project_mapping with no rows. Additionally, the repo scope
condition did not check for DOMAIN_TYPE_CROSS, so selecting only
CROSS would not create a repo scope, breaking DORA metrics.

This adds the same fixes applied to GitLab in apache#8743.

Closes apache#8749
lrf-nitro pushed a commit to AkerBP/nitro-devlake that referenced this pull request Mar 9, 2026
…pesV200 (apache#8750)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopesV200 produced zero scopes,
leaving project_mapping with no repo rows. This adds the same
empty-entities default applied to GitLab in apache#8743.

Closes apache#8748
klesh pushed a commit that referenced this pull request Mar 12, 2026
* feat(github): auto-refresh GitHub App installation tokens

Add transport-level token refresh for GitHub App (AppKey) connections.
GitHub App installation tokens expire after ~1 hour; this adds proactive
refresh (before expiry) and reactive refresh (on 401) using the existing
TokenProvider/RefreshRoundTripper infrastructure.

New files:
- app_installation_refresh.go: refresh logic + DB persistence
- refresh_api_client.go: minimal ApiClient for token refresh POST
- cmd/test_refresh/main.go: manual test script for real GitHub Apps

Modified:
- connection.go: export GetInstallationAccessToken, parse ExpiresAt
- token_provider.go: add refreshFn for pluggable refresh strategies
- round_tripper.go: document dual Authorization header interaction
- api_client.go: wire AppKey connections into refresh infrastructure
- Tests updated for new constructors and AppKey refresh flow

* feat(github): add diagnostic logging to GitHub App token refresh

Add structured logging at key decision points for token refresh:
- Token provider creation (connection ID, installation ID, expiry)
- Round tripper installation (connection ID, auth method)
- Proactive refresh trigger (near-expiry detection)
- Refresh start/success/failure (old/new token prefixes, expiry times)
- DB persistence success/failure
- Reactive 401 refresh and skip-due-to-concurrent-refresh

All logs route through the DevLake logger to pipeline log files.

* fix(github): prevent deadlock and fix token persistence in App token refresh

Deadlock fix: NewAppInstallationTokenProvider now captures client.Transport
(the base transport) before wrapping with RefreshRoundTripper. The refresh
function uses newRefreshApiClientWithTransport(baseTransport) to POST for
new installation tokens, bypassing the RefreshRoundTripper entirely.

Token persistence fix: PersistEncryptedTokenColumns() manually encrypts
tokens via plugin.Encrypt() then writes ciphertext via dal.UpdateColumns
with conn.TableName() (a string) as the first argument. Passing the table
name string makes GORM use Table() instead of Model(), preventing the
encdec serializer from corrupting the in-memory token value. The encryption
secret is threaded from taskCtx.GetConfig(ENCRYPTION_SECRET) through
CreateApiClient to TokenProvider to persist functions.

Also persists the initial App token at startup for DB consistency, and
adds TestProactiveRefreshNoDeadlock with a real RSA key to verify the
deadlock scenario is resolved.

* fix(grafana): update dashboard descriptions to list all supported data sources (#8741)

Several dashboard introduction panels hardcoded "GitHub and Jira" as
required data sources, even though the underlying queries use generic
domain layer tables that work with any supported Git tool or issue
tracker. Updated to list all supported sources following the pattern
already used by DORA and WorkLogs dashboards.

Closes #8740

Co-authored-by: Spiff Azeta <spiffazeta@gmail.com>

* fix: modify cicd_deployments name from varchar to text (#8724)

* fix: modify cicd_deployments name from varchar to text

* fix: update the year

* fix(q_dev): replace MariaDB-specific IF NOT EXISTS syntax with DAL methods for MySQL 8.x compatibility (#8745)

* fix(azuredevops): default empty entities and add CROSS to repo scope in makeScopeV200 (#8751)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopeV200 produced zero scopes,
leaving project_mapping with no rows. Additionally, the repo scope
condition did not check for DOMAIN_TYPE_CROSS, so selecting only
CROSS would not create a repo scope, breaking DORA metrics.

This adds the same fixes applied to GitLab in #8743.

Closes #8749

* fix(bitbucket): default empty entities to all domain types in makeScopesV200 (#8750)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopesV200 produced zero scopes,
leaving project_mapping with no repo rows. This adds the same
empty-entities default applied to GitLab in #8743.

Closes #8748

* fix(github): remove unused refresh client constructor and update tests

---------

Co-authored-by: Spiff Azeta <35563797+spiffaz@users.noreply.github.com>
Co-authored-by: Spiff Azeta <spiffazeta@gmail.com>
Co-authored-by: Dan Crews <crewsd@gmail.com>
Co-authored-by: Tomoya Kawaguchi <68677002+yamoyamoto@users.noreply.github.com>
la-tamas pushed a commit to archfz/incubator-devlake that referenced this pull request Mar 26, 2026
GitLab's makeScopeV200 did not create a repos scope when
scopeConfig.Entities was empty or only contained CROSS. This
caused project_mapping to have no table='repos' row, breaking
downstream DORA metrics, PR-issue linking, and all PR dashboard
panels that join on project_mapping.

The fix aligns GitLab with the GitHub plugin by:
1. Defaulting empty entities to plugin.DOMAIN_TYPES
2. Adding DOMAIN_TYPE_CROSS to the repo scope condition

Closes apache#8742

Co-authored-by: Spiff Azeta <spiffazeta@gmail.com>
la-tamas pushed a commit to archfz/incubator-devlake that referenced this pull request Mar 26, 2026
…in makeScopeV200 (apache#8751)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopeV200 produced zero scopes,
leaving project_mapping with no rows. Additionally, the repo scope
condition did not check for DOMAIN_TYPE_CROSS, so selecting only
CROSS would not create a repo scope, breaking DORA metrics.

This adds the same fixes applied to GitLab in apache#8743.

Closes apache#8749
la-tamas pushed a commit to archfz/incubator-devlake that referenced this pull request Mar 26, 2026
…pesV200 (apache#8750)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopesV200 produced zero scopes,
leaving project_mapping with no repo rows. This adds the same
empty-entities default applied to GitLab in apache#8743.

Closes apache#8748
la-tamas pushed a commit to archfz/incubator-devlake that referenced this pull request Mar 26, 2026
* feat(github): auto-refresh GitHub App installation tokens

Add transport-level token refresh for GitHub App (AppKey) connections.
GitHub App installation tokens expire after ~1 hour; this adds proactive
refresh (before expiry) and reactive refresh (on 401) using the existing
TokenProvider/RefreshRoundTripper infrastructure.

New files:
- app_installation_refresh.go: refresh logic + DB persistence
- refresh_api_client.go: minimal ApiClient for token refresh POST
- cmd/test_refresh/main.go: manual test script for real GitHub Apps

Modified:
- connection.go: export GetInstallationAccessToken, parse ExpiresAt
- token_provider.go: add refreshFn for pluggable refresh strategies
- round_tripper.go: document dual Authorization header interaction
- api_client.go: wire AppKey connections into refresh infrastructure
- Tests updated for new constructors and AppKey refresh flow

* feat(github): add diagnostic logging to GitHub App token refresh

Add structured logging at key decision points for token refresh:
- Token provider creation (connection ID, installation ID, expiry)
- Round tripper installation (connection ID, auth method)
- Proactive refresh trigger (near-expiry detection)
- Refresh start/success/failure (old/new token prefixes, expiry times)
- DB persistence success/failure
- Reactive 401 refresh and skip-due-to-concurrent-refresh

All logs route through the DevLake logger to pipeline log files.

* fix(github): prevent deadlock and fix token persistence in App token refresh

Deadlock fix: NewAppInstallationTokenProvider now captures client.Transport
(the base transport) before wrapping with RefreshRoundTripper. The refresh
function uses newRefreshApiClientWithTransport(baseTransport) to POST for
new installation tokens, bypassing the RefreshRoundTripper entirely.

Token persistence fix: PersistEncryptedTokenColumns() manually encrypts
tokens via plugin.Encrypt() then writes ciphertext via dal.UpdateColumns
with conn.TableName() (a string) as the first argument. Passing the table
name string makes GORM use Table() instead of Model(), preventing the
encdec serializer from corrupting the in-memory token value. The encryption
secret is threaded from taskCtx.GetConfig(ENCRYPTION_SECRET) through
CreateApiClient to TokenProvider to persist functions.

Also persists the initial App token at startup for DB consistency, and
adds TestProactiveRefreshNoDeadlock with a real RSA key to verify the
deadlock scenario is resolved.

* fix(grafana): update dashboard descriptions to list all supported data sources (apache#8741)

Several dashboard introduction panels hardcoded "GitHub and Jira" as
required data sources, even though the underlying queries use generic
domain layer tables that work with any supported Git tool or issue
tracker. Updated to list all supported sources following the pattern
already used by DORA and WorkLogs dashboards.

Closes apache#8740

Co-authored-by: Spiff Azeta <spiffazeta@gmail.com>

* fix: modify cicd_deployments name from varchar to text (apache#8724)

* fix: modify cicd_deployments name from varchar to text

* fix: update the year

* fix(q_dev): replace MariaDB-specific IF NOT EXISTS syntax with DAL methods for MySQL 8.x compatibility (apache#8745)

* fix(azuredevops): default empty entities and add CROSS to repo scope in makeScopeV200 (apache#8751)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopeV200 produced zero scopes,
leaving project_mapping with no rows. Additionally, the repo scope
condition did not check for DOMAIN_TYPE_CROSS, so selecting only
CROSS would not create a repo scope, breaking DORA metrics.

This adds the same fixes applied to GitLab in apache#8743.

Closes apache#8749

* fix(bitbucket): default empty entities to all domain types in makeScopesV200 (apache#8750)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopesV200 produced zero scopes,
leaving project_mapping with no repo rows. This adds the same
empty-entities default applied to GitLab in apache#8743.

Closes apache#8748

* fix(github): remove unused refresh client constructor and update tests

---------

Co-authored-by: Spiff Azeta <35563797+spiffaz@users.noreply.github.com>
Co-authored-by: Spiff Azeta <spiffazeta@gmail.com>
Co-authored-by: Dan Crews <crewsd@gmail.com>
Co-authored-by: Tomoya Kawaguchi <68677002+yamoyamoto@users.noreply.github.com>
la-tamas pushed a commit to archfz/incubator-devlake that referenced this pull request Apr 9, 2026
GitLab's makeScopeV200 did not create a repos scope when
scopeConfig.Entities was empty or only contained CROSS. This
caused project_mapping to have no table='repos' row, breaking
downstream DORA metrics, PR-issue linking, and all PR dashboard
panels that join on project_mapping.

The fix aligns GitLab with the GitHub plugin by:
1. Defaulting empty entities to plugin.DOMAIN_TYPES
2. Adding DOMAIN_TYPE_CROSS to the repo scope condition

Closes apache#8742

Co-authored-by: Spiff Azeta <spiffazeta@gmail.com>
la-tamas pushed a commit to archfz/incubator-devlake that referenced this pull request Apr 9, 2026
…in makeScopeV200 (apache#8751)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopeV200 produced zero scopes,
leaving project_mapping with no rows. Additionally, the repo scope
condition did not check for DOMAIN_TYPE_CROSS, so selecting only
CROSS would not create a repo scope, breaking DORA metrics.

This adds the same fixes applied to GitLab in apache#8743.

Closes apache#8749
la-tamas pushed a commit to archfz/incubator-devlake that referenced this pull request Apr 9, 2026
…pesV200 (apache#8750)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopesV200 produced zero scopes,
leaving project_mapping with no repo rows. This adds the same
empty-entities default applied to GitLab in apache#8743.

Closes apache#8748
la-tamas pushed a commit to archfz/incubator-devlake that referenced this pull request Apr 9, 2026
* feat(github): auto-refresh GitHub App installation tokens

Add transport-level token refresh for GitHub App (AppKey) connections.
GitHub App installation tokens expire after ~1 hour; this adds proactive
refresh (before expiry) and reactive refresh (on 401) using the existing
TokenProvider/RefreshRoundTripper infrastructure.

New files:
- app_installation_refresh.go: refresh logic + DB persistence
- refresh_api_client.go: minimal ApiClient for token refresh POST
- cmd/test_refresh/main.go: manual test script for real GitHub Apps

Modified:
- connection.go: export GetInstallationAccessToken, parse ExpiresAt
- token_provider.go: add refreshFn for pluggable refresh strategies
- round_tripper.go: document dual Authorization header interaction
- api_client.go: wire AppKey connections into refresh infrastructure
- Tests updated for new constructors and AppKey refresh flow

* feat(github): add diagnostic logging to GitHub App token refresh

Add structured logging at key decision points for token refresh:
- Token provider creation (connection ID, installation ID, expiry)
- Round tripper installation (connection ID, auth method)
- Proactive refresh trigger (near-expiry detection)
- Refresh start/success/failure (old/new token prefixes, expiry times)
- DB persistence success/failure
- Reactive 401 refresh and skip-due-to-concurrent-refresh

All logs route through the DevLake logger to pipeline log files.

* fix(github): prevent deadlock and fix token persistence in App token refresh

Deadlock fix: NewAppInstallationTokenProvider now captures client.Transport
(the base transport) before wrapping with RefreshRoundTripper. The refresh
function uses newRefreshApiClientWithTransport(baseTransport) to POST for
new installation tokens, bypassing the RefreshRoundTripper entirely.

Token persistence fix: PersistEncryptedTokenColumns() manually encrypts
tokens via plugin.Encrypt() then writes ciphertext via dal.UpdateColumns
with conn.TableName() (a string) as the first argument. Passing the table
name string makes GORM use Table() instead of Model(), preventing the
encdec serializer from corrupting the in-memory token value. The encryption
secret is threaded from taskCtx.GetConfig(ENCRYPTION_SECRET) through
CreateApiClient to TokenProvider to persist functions.

Also persists the initial App token at startup for DB consistency, and
adds TestProactiveRefreshNoDeadlock with a real RSA key to verify the
deadlock scenario is resolved.

* fix(grafana): update dashboard descriptions to list all supported data sources (apache#8741)

Several dashboard introduction panels hardcoded "GitHub and Jira" as
required data sources, even though the underlying queries use generic
domain layer tables that work with any supported Git tool or issue
tracker. Updated to list all supported sources following the pattern
already used by DORA and WorkLogs dashboards.

Closes apache#8740

Co-authored-by: Spiff Azeta <spiffazeta@gmail.com>

* fix: modify cicd_deployments name from varchar to text (apache#8724)

* fix: modify cicd_deployments name from varchar to text

* fix: update the year

* fix(q_dev): replace MariaDB-specific IF NOT EXISTS syntax with DAL methods for MySQL 8.x compatibility (apache#8745)

* fix(azuredevops): default empty entities and add CROSS to repo scope in makeScopeV200 (apache#8751)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopeV200 produced zero scopes,
leaving project_mapping with no rows. Additionally, the repo scope
condition did not check for DOMAIN_TYPE_CROSS, so selecting only
CROSS would not create a repo scope, breaking DORA metrics.

This adds the same fixes applied to GitLab in apache#8743.

Closes apache#8749

* fix(bitbucket): default empty entities to all domain types in makeScopesV200 (apache#8750)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopesV200 produced zero scopes,
leaving project_mapping with no repo rows. This adds the same
empty-entities default applied to GitLab in apache#8743.

Closes apache#8748

* fix(github): remove unused refresh client constructor and update tests

---------

Co-authored-by: Spiff Azeta <35563797+spiffaz@users.noreply.github.com>
Co-authored-by: Spiff Azeta <spiffazeta@gmail.com>
Co-authored-by: Dan Crews <crewsd@gmail.com>
Co-authored-by: Tomoya Kawaguchi <68677002+yamoyamoto@users.noreply.github.com>
zvika-finally pushed a commit to zvika-finally/incubator-devlake that referenced this pull request Apr 30, 2026
GitLab's makeScopeV200 did not create a repos scope when
scopeConfig.Entities was empty or only contained CROSS. This
caused project_mapping to have no table='repos' row, breaking
downstream DORA metrics, PR-issue linking, and all PR dashboard
panels that join on project_mapping.

The fix aligns GitLab with the GitHub plugin by:
1. Defaulting empty entities to plugin.DOMAIN_TYPES
2. Adding DOMAIN_TYPE_CROSS to the repo scope condition

Closes apache#8742

Co-authored-by: Spiff Azeta <spiffazeta@gmail.com>
zvika-finally pushed a commit to zvika-finally/incubator-devlake that referenced this pull request Apr 30, 2026
…pesV200 (apache#8750)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopesV200 produced zero scopes,
leaving project_mapping with no repo rows. This adds the same
empty-entities default applied to GitLab in apache#8743.

Closes apache#8748
zvika-finally pushed a commit to zvika-finally/incubator-devlake that referenced this pull request Apr 30, 2026
…in makeScopeV200 (apache#8751)

When scopeConfig.Entities is empty (common when no entities are
explicitly selected in the UI), makeScopeV200 produced zero scopes,
leaving project_mapping with no rows. Additionally, the repo scope
condition did not check for DOMAIN_TYPE_CROSS, so selecting only
CROSS would not create a repo scope, breaking DORA metrics.

This adds the same fixes applied to GitLab in apache#8743.

Closes apache#8749
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/plugins This issue or PR relates to plugins pr-type/bug-fix This PR fixes a bug severity/p0 This bug blocks key user journey and function size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][GitLab] Missing repos row in project_mapping breaks PR dashboards and DORA metrics

2 participants